package simple.utils.bitmaps;

import org.apache.commons.lang.ArrayUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created with IntelliJ IDEA.
 * User: rehak
 * Date: 9/26/13
 * Time: 9:39 AM
 * To change this template use File | Settings | File Templates.
 */
public class BitmapFactory {

    private static final Map<Class, Byte> m = new ConcurrentHashMap<>();
    private static final Map<Byte, Class> rm = new ConcurrentHashMap<>();

    static {
        put(BitmapBitSet.class, (byte) 0);
        put(BitmapEWAH.class, (byte) 1);
    }

    private BitmapFactory() {
        throw new IllegalStateException("Uninvokable");
    }

    private static void put(Class cls, Byte b) {
        m.put(cls, b);
        rm.put(b, cls);
    }

    public static BitmapBitSet newBitmapBitSet() {
        return new BitmapBitSet();
    }

    public static BitmapEWAH newBitmapEWAH() {
        return new BitmapEWAH();
    }

    public static Bitmap deserialize(byte[] data) throws IOException {
        return deserialize(data, Runtime.getRuntime().availableProcessors());
    }

    public static Bitmap deserialize(byte[] data, int concurrencyLevel) throws IOException {
        byte t = data[0];
        Class cls = rm.get(t);
        if (cls == null) {
            throw new IllegalArgumentException("Unknown bitmap type " + t);
        }
        return create(cls, Arrays.copyOfRange(data, 1, data.length), concurrencyLevel);

    }

    private static Bitmap create(Class cls, byte[] bytes, int concurrencyLevel) throws IOException {
        if (cls.equals(BitmapBitSet.class)) {
            return BitmapBitSet.fromBytes(bytes);
        } else if (cls.equals(BitmapEWAH.class)) {
            return BitmapEWAH.fromBytes(bytes, concurrencyLevel);
        } else {
            throw new IllegalArgumentException("Unknown class " + cls);
        }
    }

    public static byte[] serialize(Bitmap bitmap) throws IOException {
        byte[] bytes = bitmap.toBytes();
        Byte n = m.get(bitmap.getClass());
        if (n == null) {
            throw new IllegalArgumentException("Unknown bitmap class " + bitmap.getClass());
        }
        return ArrayUtils.addAll(new byte[]{n.byteValue()}, bytes);
    }


}
